package com.gitee.clarence.swagger;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.util.CollectionUtils;

import com.gitee.clarence.entity.WrapSwagger;
import com.gitee.clarence.swagger.properties.SwaggerProperties;
import com.gitee.clarence.swagger.utils.JavaSourceUtils;
import com.gitee.clarence.swagger.utils.SourceReader;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.parser.ParseException;

import io.swagger.models.Operation;
import io.swagger.models.Path;
import io.swagger.models.Swagger;
import io.swagger.models.parameters.Parameter;

/**
 * Created by IntelliJ IDEA. User: luopeng Date: 2017-07-18 上午10:14
 */
public class SwaggerSourceParse {

	private Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	private ApplicationContext configurableApplicationContext;

	@Autowired
	private SwaggerProperties swaggerProperties;

	private Map<String, List<Parameter>> params = new HashMap<String, List<Parameter>>();
	
	//private List<String> methods = new ArrayList<String>();

	private static final String DEFAULT_DIR = "source";

	public WrapSwagger parseJarSource() {
		String sourceDir = DEFAULT_DIR;
		if (StringUtils.isNoneBlank(swaggerProperties.getSourceDir()))
			sourceDir = swaggerProperties.getSourceDir();
		File file = new File(sourceDir);
		File[] files = file.listFiles();
		List<JavaClass> javaClassList = new ArrayList<>();
		if (files != null) {
			for (File file1 : files) {
				if (file1.isDirectory())
					continue;
				try {
					List<JavaClass> list = SourceReader.readFile(file1);
					javaClassList.addAll(list);
				} catch (IOException e) {
					logger.warn("", e);
					continue;
				}
			}
		}
		List<File> projectFiles = JavaSourceUtils.listProjectJavaFile();
		
		
		Map<String, JavaClass> projectJavaClassMap = new HashMap<>();
		try {
			Map<String, JavaClass> javaClassMap = SourceReader
					.transforJavaClass(SourceReader.readJavaFiles(projectFiles));
			if (javaClassMap != null)
				projectJavaClassMap.putAll(javaClassMap);
		} catch (IOException | ParseException e) {
			logger.info("", e);
		}
		Map<String, JavaClass> javaClassMap = SourceReader.transforJavaClass(javaClassList);
		if (javaClassMap != null)
			projectJavaClassMap.putAll(javaClassMap);
		Swagger swagger = new SpringNewDocReader(new Swagger()).read(projectJavaClassMap,
				configurableApplicationContext);
		WrapSwagger wrapSwagger = new WrapSwagger();
		BeanUtils.copyProperties(swagger, wrapSwagger);
		wrapSwagger.process();
		return wrapSwagger;
	}

	public Map<String, List<Parameter>> getParams() {

		WrapSwagger wrapSwagger = parseJarSource();
		Map<String, Path> paths = wrapSwagger.getPaths();
		Set<Entry<String, Path>> pathEntrySet = paths.entrySet();
		for (Entry<String, Path> entry : pathEntrySet) {
			// String key = entry.getKey();
			Path path = entry.getValue();
			parseParams(path.getGet());
			parseParams(path.getPost());
			parseParams(path.getPut());
			parseParams(path.getDelete());
			logger.info("---------------------------------------------");
		}
		return params;
	}
	
	public  List<Parameter> getParam(String method) {
		if(CollectionUtils.isEmpty(params)){
			getParams();
		}
		return params.get(method);
	}
	
	public  List<String> methods() {
		if(CollectionUtils.isEmpty(params)){
			getParams();
		}
		Set<Entry<String, List<Parameter>>> entrySet = params.entrySet();
		List<String> methods = new ArrayList<String>();
		for (Entry<String, List<Parameter>> entry : entrySet) {
			methods.add(entry.getKey());
		}
		Collections.sort(methods);
		return methods;
	}
	
	private void parseParams(Operation operation){
		
		if(null==operation){
			return;
		}
		String tag = operation.getTags().get(0);
		String operationId = operation.getOperationId();
		List<Parameter> parameters = operation.getParameters();
		
		String methodName =  tag+"-"+operationId;
		
		params.put(methodName, parameters);
		
		//methods.add(methodName);
	}
	

}
